#include "Debug.h"
#include "TriangleBase.h"
#include "VertexBase.h"
#include "EdgeBase.h"

TriangleBase::TriangleBase(MItMeshPolygon* _faceIt, MItMeshVertex* _vertsIt, int _faceNumber, VertexBase* _A, VertexBase* _B, VertexBase* _C, EdgeBase* _ab, EdgeBase* _bc, EdgeBase* _ca)
{
	faceNumber = _faceNumber;
	A = _A;
	B = _B;
	C = _C;
	abEdge = _ab;
	bcEdge = _bc;
	caEdge = _ca;

	MVector ab(A->getPos() - B->getPos());
	MVector ac(A->getPos() - C->getPos());
	MVector ba(B->getPos() - A->getPos());
	MVector bc(B->getPos() - C->getPos());
	MVector ca(C->getPos() - A->getPos());
	MVector cb(C->getPos() - B->getPos());
	double aAngle = ab.angle(ac) * 180 / M_PI;
	double bAngle = ba.angle(bc) * 180 / M_PI;
	double cAngle = ca.angle(cb) * 180 / M_PI;		

	A->addTriangleParent(this, aAngle);
	B->addTriangleParent(this, bAngle);
	C->addTriangleParent(this, cAngle);

	points.push_back(A);
	points.push_back(B);
	points.push_back(C);	
	if(abEdge != NULL)
	{
		sides.push_back(abEdge);
		sides.push_back(bcEdge);
		sides.push_back(caEdge);
	}
}

void TriangleBase::setOptimalAngles()
{
	A->setOptimalAngle(this);
	B->setOptimalAngle(this);
	C->setOptimalAngle(this);
}

//Default constructer
TriangleBase::TriangleBase()
{
}

TriangleBase::~TriangleBase(void)
{
}
void TriangleBase::updateAngles(angleTriple triple)
{
	A->setAngle(this, triple.A);
	B->setAngle(this, triple.B);
	C->setAngle(this, triple.C);
}

double TriangleBase::getAngularDistortion()
{
	double distortion =0;
	distortion += A->getAngularDistortionInTriangle(this);
	distortion += B->getAngularDistortionInTriangle(this);
	distortion += C->getAngularDistortionInTriangle(this);
	return distortion;
}

TriangleBase::angleTriple TriangleBase::getAngles()
{
	angleTriple triple;
	triple.A = A->getAngle(this);
	triple.B = B->getAngle(this);
	triple.C = C->getAngle(this);
	return triple;
}

int TriangleBase::getNum()
{
	return faceNumber;
}

void TriangleBase::printContents()
{
	cout << "Tri: " << faceNumber << "\t";
	cout << "\tA: "; A->printContents(this);
	cout << "\tB: "; B->printContents(this);
	cout << "\tC: "; C->printContents(this); cout << "\tTot: " << sumAngles() << " Dist: " << getAngularDistortion() << endl;
}

double TriangleBase::sumAngles()
{
	return A->getAngle(this) + B->getAngle(this) + C->getAngle(this);
}

double TriangleBase::getPrevAngle(VertexBase* input)
{
	char angleName = findAngleName(input);
	if(angleName == 'A')
		return C->getAngle(this);
	if(angleName == 'B')
		return A->getAngle(this);
	if(angleName == 'C')
		return B->getAngle(this);
	return -1;
}

double TriangleBase::getNextAngle(VertexBase* input)
{
	char angleName = findAngleName(input);
	if(angleName == 'A')
		return B->getAngle(this);
	if(angleName == 'B')
		return C->getAngle(this);
	if(angleName == 'C')
		return A->getAngle(this);
	return -1;
}

char TriangleBase::findAngleName(VertexBase* input)
{
	if(input == A)
		return 'A';
	if(input == B)
		return 'B';
	if(input == C)
		return 'C';
	return -1;
}

bool TriangleBase::inRadiusOf(VertexBase* vertex, double radius)
{
	MPoint pos = vertex->getPos();
	if( (pos.distanceTo(A->getPos()) <= radius) &&
		(pos.distanceTo(B->getPos()) <= radius) &&
		(pos.distanceTo(C->getPos()) <= radius) )
		return true;
	return false;
}

vector<VertexBase*> TriangleBase::getCorners()
{	
	return points;
}

vector<EdgeBase*> TriangleBase::getSides()
{	
	return sides;
}

MIntArray* TriangleBase::getAdjacentFaceIndices()
{
	MIntArray* indices= new MIntArray() ;
	Utilities::faceItGet(faceNumber)->getConnectedFaces(*indices);
	return indices;
}

EdgeBase* TriangleBase::getABEdge()
{
	return abEdge;
}